home *** CD-ROM | disk | FTP | other *** search
/ NeXT Education Software Sampler 1992 Fall / NeXT Education Software Sampler 1992 Fall.iso / Programming / Source / winterp-1.13 / src-server / xlisp / xlmath.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-10-04  |  12.1 KB  |  463 lines

  1. /* -*-C-*-
  2. ********************************************************************************
  3. *
  4. * File:         xlmath.c
  5. * RCS:          $Header: xlmath.c,v 1.5 91/03/24 22:25:12 mayer Exp $
  6. * Description:  xlisp built-in arithmetic functions
  7. * Author:       David Michael Betz
  8. * Created:      
  9. * Modified:     Fri Oct  4 04:06:29 1991 (Niels Mayer) mayer@hplnpm
  10. * Language:     C
  11. * Package:      N/A
  12. * Status:       X11r5 contrib tape release
  13. *
  14. * WINTERP Copyright 1989, 1990, 1991 Hewlett-Packard Company (by Niels Mayer).
  15. * XLISP version 2.1, Copyright (c) 1989, by David Betz.
  16. *
  17. * Permission to use, copy, modify, distribute, and sell this software and its
  18. * documentation for any purpose is hereby granted without fee, provided that
  19. * the above copyright notice appear in all copies and that both that
  20. * copyright notice and this permission notice appear in supporting
  21. * documentation, and that the name of Hewlett-Packard and David Betz not be
  22. * used in advertising or publicity pertaining to distribution of the software
  23. * without specific, written prior permission.  Hewlett-Packard and David Betz
  24. * make no representations about the suitability of this software for any
  25. * purpose. It is provided "as is" without express or implied warranty.
  26. *
  27. * HEWLETT-PACKARD AND DAVID BETZ DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
  28. * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS,
  29. * IN NO EVENT SHALL HEWLETT-PACKARD NOR DAVID BETZ BE LIABLE FOR ANY SPECIAL,
  30. * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
  31. * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
  32. * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
  33. * PERFORMANCE OF THIS SOFTWARE.
  34. *
  35. * See ./winterp/COPYRIGHT for information on contacting the authors.
  36. * Please send modifications, improvements and bugfixes to mayer@hplabs.hp.com
  37. * Post XLISP-specific questions/information to the newsgroup comp.lang.lisp.x
  38. *
  39. ********************************************************************************
  40. */
  41. static char rcs_identity[] = "@(#)$Header: xlmath.c,v 1.5 91/03/24 22:25:12 mayer Exp $";
  42.  
  43.  
  44. #include "xlisp.h"
  45. #include <math.h>
  46.  
  47. /* external variables */
  48. extern LVAL true;
  49.  
  50. /* forward declarations */
  51. LOCAL FORWARD LVAL unary();    /* NPM: changed this to LOCAL */
  52. LOCAL FORWARD LVAL binary();    /* NPM: changed this to LOCAL */
  53. LOCAL FORWARD LVAL predicate();    /* NPM: changed this to LOCAL */
  54. LOCAL FORWARD LVAL compare();    /* NPM: changed this to LOCAL */
  55.  
  56. /* binary functions */
  57. LVAL xadd()    { return (binary('+')); } /* + */
  58. LVAL xsub()    { return (binary('-')); } /* - */
  59. LVAL xmul()    { return (binary('*')); } /* * */
  60. LVAL xdiv()    { return (binary('/')); } /* / */
  61. LVAL xrem()    { return (binary('%')); } /* rem */
  62. LVAL xmin()    { return (binary('m')); } /* min */
  63. LVAL xmax()    { return (binary('M')); } /* max */
  64. LVAL xexpt()   { return (binary('E')); } /* expt */
  65. LVAL xlogand() { return (binary('&')); } /* logand */
  66. LVAL xlogior() { return (binary('|')); } /* logior */
  67. LVAL xlogxor() { return (binary('^')); } /* logxor */
  68.  
  69. /* xgcd - greatest common divisor */
  70. LVAL xgcd()
  71. {
  72.     FIXTYPE m,n,r;
  73.     LVAL arg;
  74.  
  75.     if (!moreargs())            /* check for identity case */
  76.     return (cvfixnum((FIXTYPE)0));
  77.     arg = xlgafixnum();
  78.     n = getfixnum(arg);
  79.     if (n < (FIXTYPE)0) n = -n;        /* absolute value */
  80.     while (moreargs()) {
  81.     arg = xlgafixnum();
  82.     m = getfixnum(arg);
  83.     if (m < (FIXTYPE)0) m = -m;    /* absolute value */
  84.     for (;;) {            /* euclid's algorithm */
  85.         r = m % n;
  86.         if (r == (FIXTYPE)0)
  87.         break;
  88.         m = n;
  89.         n = r;
  90.     }
  91.     }
  92.     return (cvfixnum(n));
  93. }
  94.  
  95. /* binary - handle binary operations */
  96. LOCAL LVAL binary(fcn)
  97.   int fcn;
  98. {
  99.     FIXTYPE ival,iarg;
  100.     FLOTYPE fval,farg;
  101.     LVAL arg;
  102.     int mode;
  103.  
  104.     /* get the first argument */
  105.     arg = xlgetarg();
  106.  
  107.     /* set the type of the first argument */
  108.     if (fixp(arg)) {
  109.     ival = getfixnum(arg);
  110.     mode = 'I';
  111.     }
  112.     else if (floatp(arg)) {
  113.     fval = getflonum(arg);
  114.     mode = 'F';
  115.     }
  116.     else
  117.     xlerror("bad argument type",arg);
  118.  
  119.     /* treat a single argument as a special case */
  120.     if (!moreargs()) {
  121.     switch (fcn) {
  122.     case '-':
  123.         switch (mode) {
  124.         case 'I':
  125.         ival = -ival;
  126.         break;
  127.         case 'F':
  128.         fval = -fval;
  129.         break;
  130.         }
  131.         break;
  132.     case '/':
  133.         switch (mode) {
  134.         case 'I':
  135.         checkizero(ival);
  136.         ival = 1 / ival;
  137.         break;
  138.         case 'F':
  139.         checkfzero(fval);
  140.         fval = 1.0 / fval;
  141.         break;
  142.         }
  143.     }
  144.     }
  145.  
  146.     /* handle each remaining argument */
  147.     while (moreargs()) {
  148.  
  149.     /* get the next argument */
  150.     arg = xlgetarg();
  151.  
  152.     /* check its type */
  153.     if (fixp(arg)) {
  154.         switch (mode) {
  155.         case 'I':
  156.             iarg = getfixnum(arg);
  157.             break;
  158.         case 'F':
  159.             farg = (FLOTYPE)getfixnum(arg);
  160.         break;
  161.         }
  162.     }
  163.     else if (floatp(arg)) {
  164.         switch (mode) {
  165.         case 'I':
  166.             fval = (FLOTYPE)ival;
  167.         farg = getflonum(arg);
  168.         mode = 'F';
  169.         break;
  170.         case 'F':
  171.             farg = getflonum(arg);
  172.         break;
  173.         }
  174.     }
  175.     else
  176.         xlerror("bad argument type",arg);
  177.  
  178.     /* accumulate the result value */
  179.     switch (mode) {
  180.     case 'I':
  181.         switch (fcn) {
  182.         case '+':    ival += iarg; break;
  183.         case '-':    ival -= iarg; break;
  184.         case '*':    ival *= iarg; break;
  185.         case '/':    checkizero(iarg); ival /= iarg; break;
  186.         case '%':    checkizero(iarg); ival %= iarg; break;
  187.         case 'M':    if (iarg > ival) ival = iarg; break;
  188.         case 'm':    if (iarg < ival) ival = iarg; break;
  189.         case '&':    ival &= iarg; break;
  190.         case '|':    ival |= iarg; break;
  191.         case '^':    ival ^= iarg; break;
  192.         default:    badiop();
  193.         }
  194.         break;
  195.     case 'F':
  196.         switch (fcn) {
  197.         case '+':    fval += farg; break;
  198.         case '-':    fval -= farg; break;
  199.         case '*':    fval *= farg; break;
  200.         case '/':    checkfzero(farg); fval /= farg; break;
  201.         case 'M':    if (farg > fval) fval = farg; break;
  202.         case 'm':    if (farg < fval) fval = farg; break;
  203.         case 'E':    fval = pow(fval,farg); break;
  204.         default:    badfop();
  205.         }
  206.             break;
  207.     }
  208.     }
  209.  
  210.     /* return the result */
  211.     switch (mode) {
  212.     case 'I':    return (cvfixnum(ival));
  213.     case 'F':    return (cvflonum(fval));
  214.     }
  215. }
  216.  
  217. /* checkizero - check for integer division by zero */
  218. LOCAL checkizero(iarg)        /* NPM: changed this to LOCAL at request of jsp@glia.biostr.washington.edu (Jeff Prothero) */
  219.   FIXTYPE iarg;
  220. {
  221.     if (iarg == 0)
  222.     xlfail("division by zero");
  223. }
  224.  
  225. /* checkfzero - check for floating point division by zero */
  226. LOCAL checkfzero(farg)        /* NPM: changed this to LOCAL at request of jsp@glia.biostr.washington.edu (Jeff Prothero) */
  227.   FLOTYPE farg;
  228. {
  229.     if (farg == 0.0)
  230.     xlfail("division by zero");
  231. }
  232.  
  233. /* checkfneg - check for square root of a negative number */
  234. LOCAL checkfneg(farg)        /* NPM: changed this to LOCAL at request of jsp@glia.biostr.washington.edu (Jeff Prothero) */
  235.   FLOTYPE farg;
  236. {
  237.     if (farg < 0.0)
  238.     xlfail("square root of a negative number");
  239. }
  240.  
  241. /* unary functions */
  242. LVAL xlognot() { return (unary('~')); } /* lognot */
  243. LVAL xabs()    { return (unary('A')); } /* abs */
  244. LVAL xadd1()   { return (unary('+')); } /* 1+ */
  245. LVAL xsub1()   { return (unary('-')); } /* 1- */
  246. LVAL xsin()    { return (unary('S')); } /* sin */
  247. LVAL xcos()    { return (unary('C')); } /* cos */
  248. LVAL xtan()    { return (unary('T')); } /* tan */
  249. LVAL xasin()   { return (unary('s')); } /* asin */
  250. LVAL xacos()   { return (unary('c')); } /* acos */
  251. LVAL xatan()   { return (unary('t')); } /* atan */
  252. LVAL xexp()    { return (unary('E')); } /* exp */
  253. LVAL xsqrt()   { return (unary('R')); } /* sqrt */
  254. LVAL xfix()    { return (unary('I')); } /* truncate */
  255. LVAL xfloat()  { return (unary('F')); } /* float */
  256. LVAL xrand()   { return (unary('?')); } /* random */
  257.  
  258. /* unary - handle unary operations */
  259. LOCAL LVAL unary(fcn)
  260.   int fcn;
  261. {
  262.     FLOTYPE fval;
  263.     FIXTYPE ival;
  264.     LVAL arg;
  265.  
  266.     /* get the argument */
  267.     arg = xlgetarg();
  268.     xllastarg();
  269.  
  270.     /* check its type */
  271.     if (fixp(arg)) {
  272.     ival = getfixnum(arg);
  273.     switch (fcn) {
  274.     case '~':    ival = ~ival; break;
  275.     case 'A':    ival = (ival < 0 ? -ival : ival); break;
  276.     case '+':    ival++; break;
  277.     case '-':    ival--; break;
  278.     case 'I':    break;
  279.     case 'F':    return (cvflonum((FLOTYPE)ival));
  280.     case '?':    ival = (FIXTYPE)osrand((int)ival); break;
  281.     default:    badiop();
  282.     }
  283.     return (cvfixnum(ival));
  284.     }
  285.     else if (floatp(arg)) {
  286.     fval = getflonum(arg);
  287.     switch (fcn) {
  288.     case 'A':    fval = (fval < 0.0 ? -fval : fval); break;
  289.     case '+':    fval += 1.0; break;
  290.     case '-':    fval -= 1.0; break;
  291.     case 'S':    fval = sin(fval); break;
  292.     case 'C':    fval = cos(fval); break;
  293.     case 'T':    fval = tan(fval); break;
  294.     case 's':    fval = asin(fval); break;
  295.     case 'c':    fval = acos(fval); break;
  296.     case 't':    fval = atan(fval); break;
  297.     case 'E':    fval = exp(fval); break;
  298.     case 'R':    checkfneg(fval); fval = sqrt(fval); break;
  299.     case 'I':    return (cvfixnum((FIXTYPE)fval));
  300.     case 'F':    break;
  301.     default:    badfop();
  302.     }
  303.     return (cvflonum(fval));
  304.     }
  305.     else
  306.     xlerror("bad argument type",arg);
  307. }
  308.  
  309. /* unary predicates */
  310. LVAL xminusp() { return (predicate('-')); } /* minusp */
  311. LVAL xzerop()  { return (predicate('Z')); } /* zerop */
  312. LVAL xplusp()  { return (predicate('+')); } /* plusp */
  313. LVAL xevenp()  { return (predicate('E')); } /* evenp */
  314. LVAL xoddp()   { return (predicate('O')); } /* oddp */
  315.  
  316. /* predicate - handle a predicate function */
  317. LOCAL LVAL predicate(fcn)
  318.   int fcn;
  319. {
  320.     FLOTYPE fval;
  321.     FIXTYPE ival;
  322.     LVAL arg;
  323.  
  324.     /* get the argument */
  325.     arg = xlgetarg();
  326.     xllastarg();
  327.  
  328.     /* check the argument type */
  329.     if (fixp(arg)) {
  330.     ival = getfixnum(arg);
  331.     switch (fcn) {
  332.     case '-':    ival = (ival < 0); break;
  333.     case 'Z':    ival = (ival == 0); break;
  334.     case '+':    ival = (ival > 0); break;
  335.     case 'E':    ival = ((ival & 1) == 0); break;
  336.     case 'O':    ival = ((ival & 1) != 0); break;
  337.     default:    badiop();
  338.     }
  339.     }
  340.     else if (floatp(arg)) {
  341.     fval = getflonum(arg);
  342.     switch (fcn) {
  343.     case '-':    ival = (fval < 0); break;
  344.     case 'Z':    ival = (fval == 0); break;
  345.     case '+':    ival = (fval > 0); break;
  346.     default:    badfop();
  347.     }
  348.     }
  349.     else
  350.     xlerror("bad argument type",arg);
  351.  
  352.     /* return the result value */
  353.     return (ival ? true : NIL);
  354. }
  355.  
  356. /* comparison functions */
  357. LVAL xlss() { return (compare('<')); } /* < */
  358. LVAL xleq() { return (compare('L')); } /* <= */
  359. LVAL xequ() { return (compare('=')); } /* = */
  360. LVAL xneq() { return (compare('#')); } /* /= */
  361. LVAL xgeq() { return (compare('G')); } /* >= */
  362. LVAL xgtr() { return (compare('>')); } /* > */
  363.  
  364. /* compare - common compare function */
  365. LOCAL LVAL compare(fcn)
  366.   int fcn;
  367. {
  368.     FIXTYPE icmp,ival,iarg;
  369.     FLOTYPE fcmp,fval,farg;
  370.     LVAL arg;
  371.     int mode;
  372.  
  373.     /* get the first argument */
  374.     arg = xlgetarg();
  375.  
  376.     /* set the type of the first argument */
  377.     if (fixp(arg)) {
  378.     ival = getfixnum(arg);
  379.     mode = 'I';
  380.     }
  381.     else if (floatp(arg)) {
  382.     fval = getflonum(arg);
  383.     mode = 'F';
  384.     }
  385.     else
  386.     xlerror("bad argument type",arg);
  387.  
  388.     /* handle each remaining argument */
  389.     for (icmp = TRUE; icmp && moreargs(); ival = iarg, fval = farg) {
  390.  
  391.     /* get the next argument */
  392.     arg = xlgetarg();
  393.  
  394.     /* check its type */
  395.     if (fixp(arg)) {
  396.         switch (mode) {
  397.         case 'I':
  398.             iarg = getfixnum(arg);
  399.             break;
  400.         case 'F':
  401.             farg = (FLOTYPE)getfixnum(arg);
  402.         break;
  403.         }
  404.     }
  405.     else if (floatp(arg)) {
  406.         switch (mode) {
  407.         case 'I':
  408.             fval = (FLOTYPE)ival;
  409.         farg = getflonum(arg);
  410.         mode = 'F';
  411.         break;
  412.         case 'F':
  413.             farg = getflonum(arg);
  414.         break;
  415.         }
  416.     }
  417.     else
  418.         xlerror("bad argument type",arg);
  419.  
  420.     /* compute result of the compare */
  421.     switch (mode) {
  422.     case 'I':
  423.         icmp = ival - iarg;
  424.         switch (fcn) {
  425.         case '<':    icmp = (icmp < 0); break;
  426.         case 'L':    icmp = (icmp <= 0); break;
  427.         case '=':    icmp = (icmp == 0); break;
  428.         case '#':    icmp = (icmp != 0); break;
  429.         case 'G':    icmp = (icmp >= 0); break;
  430.         case '>':    icmp = (icmp > 0); break;
  431.         }
  432.         break;
  433.     case 'F':
  434.         fcmp = fval - farg;
  435.         switch (fcn) {
  436.         case '<':    icmp = (fcmp < 0.0); break;
  437.         case 'L':    icmp = (fcmp <= 0.0); break;
  438.         case '=':    icmp = (fcmp == 0.0); break;
  439.         case '#':    icmp = (fcmp != 0.0); break;
  440.         case 'G':    icmp = (fcmp >= 0.0); break;
  441.         case '>':    icmp = (fcmp > 0.0); break;
  442.         }
  443.         break;
  444.     }
  445.     }
  446.  
  447.     /* return the result */
  448.     return (icmp ? true : NIL);
  449. }
  450.  
  451. /* badiop - bad integer operation */
  452. LOCAL badiop()
  453. {
  454.     xlfail("bad integer operation");
  455. }
  456.  
  457. /* badfop - bad floating point operation */
  458. LOCAL badfop()
  459. {
  460.     xlfail("bad floating point operation");
  461. }
  462.